
import java.awt.geom.Point2D;
import java.util.*;
import java.io.*;
public class homework_last {
	public static void main(String[] args) {
		System.out.println("随机生成10个不同的图形（图形参数自定义）");
		GeoManger a=new GeoManger();
		Random ran=new Random();
		@SuppressWarnings("resource")
		Scanner scan=new Scanner(System.in);
		for(int i=0;i<10;i++)
		{ 
		 int num=ran.nextInt(4)+1;
		 switch (num){
		 case 1:
		 {   try
		     {
			 System.out.println("矩形   请输入长和宽：");
			 double y,z;
		     y=scan.nextDouble();
		     z=scan.nextDouble();
			 Rectangle aR=new Rectangle(y, z);
			 a.Add(aR);
			 break;
		 }
		 catch (RectangleException e) {
			 System.out.println("该矩形长和宽分别为："+e.longth+" "+e.width+"     创建失败：边长不能为负数！");
			  i--;
		}
		 }
		 case 2:{
			 try {
			System.out.println("圆形   请输入圆心坐标：");
			 double x,y,z;
		     y=scan.nextDouble();
		     x=scan.nextDouble();
		     Point2D.Double b=new Point2D.Double(y, x);
		     System.out.println("请输入该圆半径：");
		     z=scan.nextDouble();
			 Circle aR=new Circle(b, z);
			 a.Add(aR);
			 break;
		 }
			 catch (InvalidRadiusException e) {
				 System.out.println("圆形边长为："+e.radius+"     创建失败：边长不能为负数！");
				 i--;
			}
		 }
		 case 3:{
			 try {
				 System.out.println("三角形   请输入三边边长：");
			double x,y,z;
			 x=scan.nextDouble();
		     y=scan.nextDouble();
		     z=scan.nextDouble();
			 Triangel aR=new Triangel(x,y,z);
			 a.Add(aR);
			 break;
		 }catch (TriangleException e) {
			 System.out.println("三角形三边边长为:"+e.x+" "+e.y+" "+e.z+"     创建失败！");
			 i--;
		}
			 }
		 case 4:{
			 try
			 {
			 int j=0;
			 System.out.println("多边形    请输入多边形的边数：");
			 j=scan.nextInt();
			 Dbx aR=new Dbx(j);
			 a.Add(aR);
		 }catch (DbxException e) {
			 e.ex();
			i--;
		}
			 }
	}
		}
		System.out.println();
		System.out.println("图形信息如下 ：");
		a.DisplayList();
		System.out.println();
		System.out.println("删除位置为（2.0，1.0）的所有图形");
		for(int i=0;i<a.getList().size();i++)
			   {
			  if(a.Remove(a.getList().get(i)))
				  i--;
		}
		System.out.println("图形信息如下（删除后）：");
		a.DisplayList();
		System.out.println();
		System.out.println("按照图形形状分类如下：");
		a.GetSort();
		a.DisplayMap();
		System.out.println();
		System.out.println("排序（分类后）：");
		a.sortMapList();
		a.DisplayMap();
		System.out.println();
		System.out.println("将图形信息写入文件（D:/冲鸭/Java/TXing.txt）中");
		String jString="D:/冲鸭/Java/TXing.txt";
		try {
			a.in(jString);
		}
		 catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println();
		try {
			a.out(jString);
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

class GeoManger {
	private Map<String, ArrayList<GeometricObject>> Map =new HashMap<String,ArrayList<GeometricObject>>();
	private List<GeometricObject> List=new ArrayList<GeometricObject>();
	public void Add(GeometricObject o) {
		List.add(o);
	}
	public boolean Remove(GeometricObject o){ 
		if(o.post.equals(new Point2D.Double(2.0,3.0)))
		{  
			List.remove(o);
			return true;
		}
		return false;
	}
	public void sortMapList() {
		for(String k:Map.keySet())
		{
			Collections.sort(Map.get(k),new Comparator<GeometricObject>() { 
				public int compare(GeometricObject o1,GeometricObject o2)
				{
					return new Double(o1.perimeter()).compareTo(o2.perimeter());
				}
			});
		}
	}
	public void DisplayList() {
		for(GeometricObject k:List)
			System.out.println(k);
	}
	public void DisplayMap() {
		for(String i:Map.keySet())
		{
			System.out.printf("%10s\n",i+":");
			for(int j=0;j<Map.get(i).size();j++)
			System.out.println('\t'+"   "+Map.get(i).get(j));
	}
	}
	public void GetSort(){
		//分类
		ArrayList<GeometricObject> rectangles=new ArrayList<GeometricObject>();
		ArrayList<GeometricObject> cicles=new ArrayList<GeometricObject>();
		ArrayList<GeometricObject> triangels=new ArrayList<GeometricObject>();
		ArrayList<GeometricObject> dbxs=new ArrayList<GeometricObject>();
		for (int i = 0; i < List.size(); i++) {
			if(List.get(i)instanceof Rectangle)
				rectangles.add(List.get(i));
			if(List.get(i)instanceof Circle)
				cicles.add(List.get(i));
			if(List.get(i)instanceof Dbx)
				dbxs.add(List.get(i));
			if(List.get(i)instanceof Triangel)
				triangels.add(List.get(i));
		}    
		 if(!rectangles.isEmpty())
			Map.put("矩形：",rectangles);
		 if(!cicles.isEmpty())
			Map.put("圆：", cicles);
		 if(!dbxs.isEmpty())
			Map.put("多边形：", dbxs);
		 if(!triangels.isEmpty())
			Map.put("三角形：", triangels);
	}
	public List<GeometricObject> getList(){
		return List;
	}
	public Map<String, ArrayList<GeometricObject>> getMap (){
		return Map;
	}
public void input(String p) throws IOException {
			BufferedWriter bu=new BufferedWriter(new FileWriter(p));
			Iterator<GeometricObject> it=List.iterator();
			while(it.hasNext()) 
			{
				bu.write(it.next().toString());
				bu.newLine(); 
			}
				bu.close();
				System.out.println("写入成功!");
}
		
	public void output(String p) throws IOException {
		    BufferedReader re=new BufferedReader(new FileReader(p));
			String q;
			while ((q=re.readLine())!=null) 
				System.out.println(q);
			re.close();
		    System.out.println("读取完成！");	
}
	public void in(String k) throws FileNotFoundException, IOException {
		ObjectOutputStream o1=new ObjectOutputStream(new FileOutputStream(k));
		for(String j:Map.keySet()) 
		{
			for(int i=0;i<Map.get(j).size();i++)
				o1.writeObject(Map.get(j).get(i));
		}
		o1.writeObject(null);//增加1个空对象 
		o1.flush();
		o1.close();
		System.out.println("写入完成！");
	}
	public void out(String k) throws FileNotFoundException, IOException, ClassNotFoundException {
		System.out.println("读取文件内容如下：");
		ObjectInputStream o1=new ObjectInputStream(new FileInputStream(k));
		Object o2=null;
		while((o2=(GeometricObject)o1.readObject())!=null) {
			GeometricObject o3=(GeometricObject) o2;
			System.out.println(o3.toString());
		}
		o1.close();
		System.out.println("读取完成");
	}
}
abstract class GeometricObject implements Comparable<GeometricObject>,Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	protected Point2D.Double post;
	public void setpost() { 
		System.out.println("图形位置为：");
		@SuppressWarnings("resource")
		Scanner scanner=new Scanner(System.in);
		double q,w;
		q=scanner.nextDouble();
		w=scanner.nextDouble();
		post=new Point2D.Double(q,w);
	}
	public int compareTo(GeometricObject o) { 
		if(perimeter()>o.perimeter())
			return 1;
		else if(perimeter()<o.perimeter())
			return -1;
		return 0;
	}
	public abstract double perimeter();
	public abstract double area();
}
class Rectangle extends GeometricObject {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double longth,width;
	public String toString() {
		return "长为"+longth+"宽为"+width+"的矩形"+"，位置为：("+post.getX()+","+post.getY()+")";
	}
	public Rectangle(double a,double b)throws RectangleException {
		if(a<=0||b<=0)
		 throw new RectangleException(a, b);
		else {
			longth=a;
			width=b;
			super.setpost();
		}
		}
	public double perimeter(){
		return (2*(longth+width));
	}
	
	public double area() {
		return (longth*width);
	}
	public void print() {
		System.out.println("矩形的周长为："+String.format("%.2f", perimeter())+"，面积为："+String.format("%.2f", area())+"，位置为："+post);
	}
}
class Circle extends GeometricObject { 
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double r;
	public Point2D.Double centalpoint;
	public Circle(Point2D.Double a,double b)throws InvalidRadiusException{
		centalpoint=a;
		post=a;
		if(b<0)
			throw new InvalidRadiusException(b);
		else {
		   r=b;
	}
	}
	public String toString() {
		return "圆心为("+centalpoint.getX()+","+centalpoint.getY()+")"+",半径为"+r+"的圆"+"，位置为：("+post.getX()+","+post.getY()+")";
	}
	public double perimeter() {
		return (Math.PI*2*r);
		}
	public double area() {
		return (Math.PI*r*r);
	}
	public void print() {
		System.out.println("圆的周长为："+String.format("%.2f", perimeter())+"，面积为："+String.format("%.2f", area())+"，位置为："+post);
	}
}
class Point implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	double x;
	double y;
	Point(double a,double b){
		x=a;
		y=b;
	}
	public boolean equals(Object o) {
		Point o1=(Point)o;
		if(this.x==o1.x)
			{if(this.y==o1.y)
				return true;}
	    return false;
	}
	public int hashCode() {
		return super.hashCode();
	}
}
class Dbx extends GeometricObject{
    /**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public int numpoint=100;
    Point []p=new Point[numpoint];
    Dbx(int h)throws DbxException {
    	if(h<3)
    		throw new DbxException(-1);
    	else {
    	@SuppressWarnings("resource")
		Scanner scan=new Scanner(System.in);
    	numpoint=h;
    	Point []ap=new Point[numpoint];
    	double e;
		double f;
    	for(int i=0;i<numpoint;i++) 
    	{System.out.println("请输入第"+(i+1)+"个顶点坐标：");
    	 e=scan.nextDouble();
		 f=scan.nextDouble();
		 ap[i]=new Point(e, f);
    	 for(int j=0;j<i;j++)
    		 if(ap[i].equals(ap[j]))
    			 throw new DbxException(i);	
    	}
    	p=ap;
    	super.setpost();
    	}
    }
    public double area() {
    	return 0;
    }
    public double perimeter() {
    	double are=0;
    	double sum1=0;
    	double sum2=0;
    	for(int i=0;i<numpoint-1;i++) {
    		sum1=Math.pow(p[i].x-p[i+1].x, 2);
    		sum2=Math.pow(p[i].y-p[i+1].y, 2);
    		are+=Math.pow(sum1+sum2, 0.5);
    	}
    	sum1=Math.pow(p[0].x-p[numpoint-1].x, 2);
    	sum2=Math.pow(p[0].y-p[numpoint-1].y, 2);
    	are+=Math.pow(sum1+sum2, 0.5);
    	return are;
    }
    public String toString() {
    	return numpoint+"边形     其位置为：("+post.getX()+","+post.getY()+")";
    }
    public void print() {
    	System.out.println("这是一个周长为"+String.format("%.2f", perimeter())+"的"+numpoint+"边形，其位置为："+post);
    }
}
class Triangel extends GeometricObject {
	//三角形
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double a,b,c;
	public Triangel(double x,double y,double z)throws TriangleException {
		if((x>0&&y>0&&z>0)&&((x+y)>z&&(x+z)>y&&(y+z)>x))
		{
		a=x;
		b=y;
		c=z;
		super.setpost();
	}
		else throw new TriangleException(x,y,z);
	}
	public String toString() {
		return "三边边长分别为："+a+"  "+b+"  "+c+"的三角形"+"  其位置为：("+post.getX()+","+post.getY()+")";
	}
	public double perimeter() {
		return (a+b+c);
		}
	public double area() {
		double p=perimeter()/2.0;
		return (Math.sqrt(p*(p-a)*(p-b)*(p-c)));
	}
	public void print() {
		System.out.println("该三角形的周长为："+String.format("%.2f", perimeter())+"   面积为："+String.format("%.2f", area())+"   位置为："+post);
	}
}
 class InvalidRadiusException extends Exception {    
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double radius;  
	public InvalidRadiusException(double radius) {             
	this.radius = radius;
	}    
}

class RectangleException extends Exception{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double longth,width;  
	public RectangleException(double lon,double wid){             
	this.longth = lon;
	width=wid;
	}    
}
class TriangleException extends Exception{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	public double x,y,z;
	public TriangleException(double a,double b,double c) {
		x=a;
		y=b;
		z=c;
	}
}
class DbxException extends Exception{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	int k;
	public DbxException(int t) {
		k=t;
	}
	public void ex() {
		if(k==-1)
			System.out.println("不构成多边形！");
		else System.out.println("不构成多边形！第"+(k+1)+"个顶坐标重复！");
	}
}
